﻿using System;
using System.IO;
using System.Web;
using System.Xml;
using System.Collections;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections.Specialized;
using SyCODE.Component.DataFactory;
using SyCODE.AjaxUpload;
using SyCODE.AjaxUpload.Providers;

namespace SyCODE.Blog.Uploader
{
    /// <summary>
    /// Upload.aspx 的处理程序
    /// 文件上传完成时的处理程序,文件保存过程由AjaxUpload实现
    /// </summary>
    public class UploadHandler : IHttpHandler
    {
        #region IHttpHandler 成员

        // 缩略图的最大宽度限制
        private const int THUMB_WIDTH = 200;
        // 缩略图的最大高度限制
        private const int THUMB_HEIGHT = 150;

        //头像的最大宽度限制
        private const int HEAD_WIDTH = 64;
        //头像的最大高度限制
        private const int HEAD_HEIGHT = 64;

        //个人形象图片的最大宽度限制,无高度限制
        private const int FACE_MAX_WIDTH = 200;

        /// <summary>
        /// 更新个人形象图片
        /// </summary>
        /// <param name="photo">个人形象图片地址</param>
        private void UpdateFace(string photo)
        {
            Updater.HeadInfo updater = new SyCODE.Blog.Updater.HeadInfo((new DirectoryInfo(Path.GetDirectoryName(photo))).Parent.Name);
            updater.SetFace(Path.GetFileName(photo));
            updater.Dispose();
        }

        /// <summary>
        /// 更新缩略图保存文件
        /// </summary>
        /// <param name="photo">图片地址</param>
        /// <param name="album">相册</param>
        /// <param name="description">图片描述</param>
        private void UpdateAlbum(string[] photos,string album)
        {
            DirectoryInfo dir = new DirectoryInfo(Path.GetDirectoryName(photos[0]));
            string albumConfig = Path.Combine(dir.Parent.FullName, "album.xml");

            XmlDocument albumDom = new XmlDocument();
            albumDom.Load(albumConfig);

            XmlNode body = albumDom.DocumentElement.SelectSingleNode("body");
            //获得相册节点
            XmlNode albumNode = body.ChildNodes[Int32.Parse(album)];

            //如果没有指定节点更新为默认节点
            if (albumNode == null)
            {
                albumNode = body.ChildNodes[0];
            }

            for (int i = 0; i < photos.Length; i++)
            {
                string photoName = Path.GetFileName(photos[i]);
                XmlElement photoNode = albumDom.CreateElement("img");
                photoNode.SetAttribute("src", HttpUtility.UrlEncode(photoName).Replace("+", "%20"));
                photoNode.SetAttribute("alt", photoName.Substring(0, photoName.LastIndexOf('.')));

                albumNode.AppendChild(photoNode);
            }
            albumDom.Save(albumConfig);

            NameValueCollection nvc = new NameValueCollection();
            nvc.Add("u", dir.Parent.Name);
            nvc.Add("id", albumNode.Attributes["id"].Value);
            nvc.Add("count", albumNode.ChildNodes.Count.ToString());
            nvc.Add("cover", albumNode.ChildNodes[Int32.Parse(albumNode.Attributes["cover"].Value)].Attributes["src"].Value);

            DBAM dbam = new DBAM();
            try
            {
                dbam.BuildParameters("updatealbum", nvc);
                dbam.Execute();
            }
            finally
            {
                dbam.Dispose();
            }
        }

        /// <summary>
        /// 创建缩略图的方法
        /// </summary>
        /// <param name="fullName">原始图片的完整路径和文件名</param>
        /// <param name="thumbFloder">缩略图文件夹名称</param>
        /// <param name="width">宽度限制</param>
        private void Thumb(string fullName, string thumbFloder, int width)
        {
            Thumb(fullName, thumbFloder, width, 0);
        }

        /// <summary>
        /// 创建缩略图的方法
        /// </summary>
        /// <param name="fullName">原始图片的完整路径和文件名</param>
        /// <param name="thumbFloder">缩略图文件夹名称</param>
        /// <param name="width">宽度限制</param>
        /// <param name="height">高度限制</param>
        private void Thumb(string fullName, string thumbFloder, int width, int height)
        {
            string outPath = Path.Combine(Path.GetDirectoryName(fullName), thumbFloder);

            if (!Directory.Exists(outPath))
                Directory.CreateDirectory(outPath);

            Image oriImg = System.Drawing.Image.FromFile(fullName), thumbImg;

            ImageFormat format = oriImg.RawFormat;

            int thumbWidth = width, thumbHeight = height;

            float scale = (float)oriImg.Width / (float)oriImg.Height;

            if (height > 0)
            {
                if (scale > (float)thumbWidth / (float)thumbHeight)
                {
                    thumbWidth = (int)Math.Round(thumbHeight * scale);
                }
                else
                {
                    thumbHeight = (int)Math.Round(thumbWidth / scale);
                }

                thumbImg = oriImg.GetThumbnailImage(thumbWidth, thumbHeight, null, IntPtr.Zero);
                oriImg.Dispose();

                Bitmap bitmap = new Bitmap(thumbImg);

                Rectangle rect = new Rectangle((int)((thumbWidth - width) / 2), (int)((thumbHeight - height) / 2), width, height);

                Bitmap outBitmap = bitmap.Clone(rect, bitmap.PixelFormat);
                bitmap.Dispose();

                outBitmap.Save(Path.Combine(outPath, Path.GetFileName(fullName)), format);

                outBitmap.Dispose();
            }
            else
            {
                thumbHeight = (int)Math.Round(thumbWidth / scale);

                thumbImg = oriImg.GetThumbnailImage(thumbWidth, thumbHeight, null, IntPtr.Zero);
                oriImg.Dispose();

                thumbImg.Save(Path.Combine(outPath, Path.GetFileName(fullName)), format);
            }
            thumbImg.Dispose();
        }

        /// <summary>
        /// 文件排斥,删除所有指定文件名外的全部文件
        /// </summary>
        /// <param name="fileName">要保留的文件名</param>
        private void Mutex(string fileName)
        {
            string oriName = Path.GetFileName(fileName);

            DirectoryInfo di = new DirectoryInfo(Path.GetDirectoryName(fileName));
            FileInfo[] files = di.GetFiles("*.*", SearchOption.TopDirectoryOnly);
            IEnumerator ienum = files.GetEnumerator();

            while (ienum.MoveNext())
            {
                FileInfo fi = (FileInfo)ienum.Current;
                if (String.Compare(fi.Name, oriName, true) != 0)
                    fi.Delete();
            }
        }

        /// <summary>
        /// 文件排斥,删除所有指定文件名外的全部文件,并将保留的文件重新命名
        /// </summary>
        /// <param name="fileName">要保留的文件名</param>
        /// <param name="newName">新文件名</param>
        private void Mutex(string fileName, string newName)
        {
            Mutex(fileName);
            File.Move(fileName, Path.Combine(Path.GetDirectoryName(fileName), newName + Path.GetExtension(fileName)));
        }

        public bool IsReusable
        {
            get
            {
                return true;
            }
        }

        public void ProcessRequest(HttpContext context)
        {
            string uploadPath = context.Request.QueryString["uploadPath"];
            UploadedFileCollection parts = HttpUploadModule.GetUploadedFiles();

            if (!String.IsNullOrEmpty(uploadPath) && parts.Count > 0)
            {

                if (String.Compare(uploadPath, "album", true) == 0)
                {
                    string[] filenames = new string[parts.Count];
                    for (int i = 0; i < parts.Count; i++)
                    {
                        UploadedFile file = parts[i];
                        FileUploadLocation location = (FileUploadLocation)file.Location;
                        string fileName = location.FileName.Replace('/', '\\');
                        filenames[i] = fileName;

                        Thumb(fileName, "Thumb", THUMB_WIDTH, THUMB_HEIGHT);

                    }
                    UpdateAlbum(filenames, context.Request.Form["album"]);
                }
                else
                {
                    UploadedFile file = parts[0];
                    FileUploadLocation location = (FileUploadLocation)file.Location;
                    string fileName = location.FileName.Replace('/', '\\');
                    if (String.Compare(uploadPath, "head", true) == 0)
                    {
                        Thumb(fileName, "", HEAD_WIDTH, HEAD_HEIGHT);
                        Mutex(fileName, "head");
                    }
                    else if (String.Compare(uploadPath, "face", true) == 0)
                    {
                        Thumb(fileName, "", FACE_MAX_WIDTH);
                        Mutex(fileName);
                        UpdateFace(fileName);
                    }
                }
            }
        }

        #endregion
    }
}